//
// security.h
// libprotea
// Tools Library for the Protea Project / User and Group security
// Copyright (C) 2003, 2004, 2005 eXegeSys, Inc.
// Copyright (C) 2008 Bruce A. James
//
// This program is part of the Protea Project.
//
// The Protea Project is free software; you can redistribute it and/or modify it 
// under the terms of the GNU General Public License as published by the 
// Free Software Foundation, either version 3 of the License, or (at your 
// option) any later version.
//
// The Protea Project is distributed in the hope that it will be useful, but 
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
// for more details.
// 
// You should have received a copy of the GNU General Public License along 
// with this program.  If not, see <http://www.gnu.org/licenses/>.
// 
// Please send correspondence to:
// 
// theproteaproject@gmail.com
//

// security.h

#ifndef __PROTEA_SECURITY_H__
#define __PROTEA_SECURITY_H__

#include "../Appdic/appdic.h"

// Forward class declarations
class XCTransactionInfo;
class __EXPORT XCAuthenticate;

namespace XERCES_CPP_NAMESPACE {
class DOMNode;
};


class __EXPORT XCUserInformation {
public:
	XCUserInformation( const char* username, const char* userpassword, const char* description, const int myindex );
	~XCUserInformation();

	char* name;
	char* password;
	char* description;
	int index;
};

class __EXPORT XCUserPointer {
public:
	XCUserInformation* info;
	XCUserPointer* next;
};

class __EXPORT XCUserList {
public:
	XCUserList();
	~XCUserList();

	XCUserInformation* Find( const char* name ) const;
	XCUserInformation* Find( const int index ) const;

	void Add( const char* name, const char* password, const char* description );
	void Remove( const XCUserInformation* user );

	XCUserPointer* GetUserList() const { return users; };
	const long GetCount() { return count; };

protected:
	int count;
	XCUserPointer* users;
};

class __EXPORT XCGroupInformation {
public:
	XCGroupInformation( const char* group_name, const char* description, const int myindex );
	~XCGroupInformation();

	bool ContainsUser( int user_index ) const;
	void AddUser( XCUserInformation* info );
	void RemoveUser( const XCUserInformation* info );

	char* name;
	char* description;
	int index;

	XCUserPointer* users;
	XCGroupInformation* next_group;
};

class __EXPORT XCGroupList {
public:
	XCGroupList();
	~XCGroupList();

	XCGroupInformation* Add( const char* name, const char* description );
	void Remove( const XCGroupInformation* group );
	void RemoveUser( const XCUserInformation* info );

	XCGroupInformation* Find( const char* name ) const;
	XCGroupInformation* Find( const int index ) const;

	XCGroupInformation* GetGroupList() const;

protected:
	int count;
	XCGroupInformation* groups;
};

class __EXPORT XCSecurityRule {
public:
	XCSecurityRule( int index, bool should_allow );

	int user_group_index;
	bool allow;
	XCSecurityRule* next_rule;
};

class __EXPORT XCSecurityRuleList : public XCBase {
public:
	XCSecurityRuleList();
	~XCSecurityRuleList();

	void Add( const XCAuthenticate* auth, const char* name, bool user, bool allow );
	void Remove( int index );

	bool ContainsUser( int user_index ) const;
	int Evaluate( const XCAuthenticate* auth, int user_index ) const;

	XCSecurityRule* rules;
	bool default_allow;
};


// Generic classes to handle transactions, capabilities and data_items
class __EXPORT XCSecurityItem : public XCSecurityRuleList {
public:
	XCSecurityItem( long number );		// Constructor

	long item_number;					// This item number
	XCSecurityItem* next;				// Linked list
};


class __EXPORT XCSecurityItems : public XCSecurityRuleList {
public:
	XCSecurityItems();
	~XCSecurityItems();

	XCSecurityItem* AddItem( long number );
	virtual void RemoveItem( const long index );

	int EvaluateItems( const XCAuthenticate* auth, int user_index, int number ) const;

	XCSecurityItem* items;
};




class __EXPORT XCSecurityApplication : public XCSecurityRuleList {
public:
	XCSecurityApplication( int app_number, bool default_allow_access );
	virtual void RemoveItem( const long index );

	int number;
	XCSecurityItems trans;
	XCSecurityItems caps;
	XCSecurityItems data_items;

	XCSecurityApplication* next;
};


class __EXPORT XCSecurityApplicationList : public XCBase {
public:
	XCSecurityApplicationList();
	~XCSecurityApplicationList();

	void AddApplication( XCSecurityApplication* app );
	XCSecurityApplication* GetApplication( int number ) const;

	void RemoveItem( const long index );

	XCSecurityApplication* applist;
};



enum AuthenticateMethod {
	AUTHENTICATE_LOCAL = 0,
	AUTHENTICATE_LDAP = 1,
	AUTHENTICATE_PAM = 2,
};


/**
	\brief Credentials storage.
	
	Maintains information on a particular user.  Automatically generated and maintained by
	the Protea system.  Use the XCTransactionVars class to access
*/
class __EXPORT XCCredentials : public XCBase {
public:
	XCCredentials( const char* username, const XCAuthenticate* security );
	~XCCredentials();

	XCSecurityApplication* AuthorizeApplication( int number );
	void AuthorizeTransaction( XCTransactionInfo* txn );

	/** 
		\brief Determines if this user has access to the supplied capability.
		Determines if this user has access to the supplied capability.

		If user fails authentication, the functions raises the error ERR_AUTHORIZATION_FAILURE
	*/
	void AuthorizeCapability( long app_number, long cap_number );

	int GetUserIndex();

	/**
		\brief Returns the current user name
		Returns a pointer to the current user name
	*/
	const char* GetUserName();
	const char* GetUserPassword();

private:
	const XCAuthenticate* myowner;
	const XCUserInformation* user;
};


class __EXPORT XCAuthenticate {
public:
	XCAuthenticate();
	virtual ~XCAuthenticate();

	void AuthClear();
	void AuthInit( const char* filename );

	XCCredentials* Authenticate( char* user, char* password );

	XCUserList users;
	XCGroupList groups;
	XCSecurityApplicationList apps;

	AuthenticateMethod auth_method;
	char* auth_parameter;

	void EncryptPassword( const char* password, char* result );

private:
	bool AuthenticateLocal( XCCredentials* creds, char* password );
	bool AuthenticateLDAP( XCCredentials* creds, char* password );
	bool AuthenticatePAM( XCCredentials* creds, char* password );

	// XML handling routines
	void HandleSecurity( XERCES_CPP_NAMESPACE::DOMNode* node );
	void HandleUserList( XERCES_CPP_NAMESPACE::DOMNode* node );
	void HandleGroupList( XERCES_CPP_NAMESPACE::DOMNode* node );
	void HandleApplication( XERCES_CPP_NAMESPACE::DOMNode* node );
	void HandleUserDef( XERCES_CPP_NAMESPACE::DOMNode* node );
	void HandleGroupDef( XERCES_CPP_NAMESPACE::DOMNode* node );

	void HandleSecurityItem( XERCES_CPP_NAMESPACE::DOMNode* node, XCSecurityItems* items );
	void HandleSecurityItems( XERCES_CPP_NAMESPACE::DOMNode* node, char* name, XCSecurityItems* items );

	void HandleRule( XERCES_CPP_NAMESPACE::DOMNode* node, XCSecurityRuleList* list );
};


#endif	// __SECURITY_H__
